package com.example.cloudkit.common;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;

/**
 * 计算工具类
 *
 * @author wo
 */
public class MathKit {

    /**
     * 格式化保留所有整数和两位小数，空的位数补0
     */
    private static final DecimalFormat DF_2 = new DecimalFormat("0.00");
    /**
     * 格式化保留所有整数和两位小数，空的位数补0，百分比形式
     */
    private static final DecimalFormat DF_2_RATIO = new DecimalFormat("0.00%");

    /**
     * 除法计算，截取保留两位小数，四舍五入
     * <p> 被除数和除数任何一个为0，结果返回0 </p>
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 商，保留两位小数，BigDecimal类型
     * @throws NumberFormatException 入参格式错误
     */
    public static BigDecimal divScale2(String v1, String v2) {
        return divScale(v1, v2, 2);
    }

    /**
     * 除法计算，截取保留两位小数，四舍五入
     * <p> 被除数和除数任何一个为0，结果返回0 </p>
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 商，保留两位小数，BigDecimal类型
     * @throws NumberFormatException 入参格式错误
     */
    public static BigDecimal divScale2(Number v1, Number v2) {
        return divScale(String.valueOf(v1), String.valueOf(v2), 2);
    }

    /**
     * 除法计算，截取保留指定位数小数，四舍五入
     * <p> 被除数和除数任何一个为0，结果返回0 </p>
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 保留几位小数
     * @return 商，BigDecimal类型
     * @throws NumberFormatException 入参格式错误
     */
    public static BigDecimal divScale(String v1, String v2, Integer scale) {
        DecimalFormat format = new DecimalFormat();
        BigDecimal b1;
        try {
            Number number = format.parse(v1);
            b1 = new BigDecimal(number.toString());
        } catch (NumberFormatException e) {
            throw new NumberFormatException("被除数格式错误，入参：" + v1);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        BigDecimal b2;
        try {
            Number number = format.parse(v2);
            b2 = new BigDecimal(number.toString());
        } catch (NumberFormatException e) {
            throw new NumberFormatException("除数格式错误，入参：" + v2);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        if (BigDecimal.ZERO.compareTo(b1) == 0 || BigDecimal.ZERO.compareTo(b2) == 0) {
            return BigDecimal.ZERO;
        }
        // 四舍五入
        return b1.divide(b2, scale, RoundingMode.HALF_UP);
    }

    /**
     * 除法计算，截取保留两位小数，四舍五入
     * <p> 被除数和除数任何一个为0，结果返回0 </p>
     * <p> 结果一定是两位小数，例如：0.00, 2.66, 3.20 ,200.00 </p>
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 商，保留两位小数，字符串类型
     * @throws NumberFormatException 入参格式错误
     */
    public static String divScale2Str(String v1, String v2) {
        BigDecimal div = divScale2(v1, v2);
        if (BigDecimal.ZERO.compareTo(div) == 0) {
            return "0.00";
        }
        return DF_2.format(div);
    }

    /**
     * 除法计算，截取保留两位小数，四舍五入，返回百分比形式
     * <p> 被除数和除数任何一个为0，结果返回0 </p>
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 商，保留两位小数，字符串类型
     * @throws NumberFormatException 入参格式错误
     */
    public static String divScale2Ratio(String v1, String v2) {
        BigDecimal div = divScale(v1, v2, 4);
        if (BigDecimal.ZERO.compareTo(div) == 0) {
            return "0.00%";
        }
        return DF_2_RATIO.format(div);
    }

    /**
     * 除法计算，截取保留两位小数，四舍五入，返回百分比形式
     * <p> 被除数和除数任何一个为0，结果返回0 </p>
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 商，保留两位小数，字符串类型
     * @throws NumberFormatException 入参格式错误
     */
    public static String divScale2Ratio(Number v1, Number v2) {
        BigDecimal div = divScale(String.valueOf(v1), String.valueOf(v2), 4);
        if (BigDecimal.ZERO.compareTo(div) == 0) {
            return "0.00%";
        }
        return DF_2_RATIO.format(div);
    }

    public static void main(String[] args) {
        BigDecimal decimal = divScale("2058", "312360", 4);
        System.out.println(decimal);
        System.out.println(DF_2_RATIO.format(decimal));
        System.out.println();

        BigDecimal bigDecimal = BigDecimal.valueOf(000.036);
        System.out.println(bigDecimal);
        System.out.println(DF_2_RATIO.format(bigDecimal));
        System.out.println();

        BigDecimal decimal1 = BigDecimal.valueOf(000.036);
        System.out.println(decimal1);
        System.out.println();

        System.out.println(divScale2Str("1", "2"));
    }

}
